<?php

namespace App\Service\Option;


use App\Models\User;
use App\Service\Page;
use Illuminate\Support\Facades\Crypt;

class Logic
{

    // 设置传递参数信息
    // 主要参数：
    //       1、传递的 $request 参数，
    //       2、传递到模板页面的 $assign 参数，
    //       3、传递缓存的参数
    //       4、传递的响应参数

    // 很多时候某些服务不能传递参数
    // 所以新建这么一个类，用于传递参数（先设置参数，然后在特定的地方使用这个参数）

    // 需要用的
    // 使用静态属性 方便多次实例化的时候，只有一次传值：其他时候实例化同样可以调用该属性的值
    protected static $options;
    protected static $app;
    protected static $request;
    protected static $data;
    //protected static $myUser;  // 用户在控制器判断

    // 页面
    protected static $assign;

    protected $error;

    // 构造方法
    public function __construct() { }

    // 设置app
    public function setApp($request)
    {
        if(empty(self::$request)){
            self::$request = $request;
        }

        return $this;
    }

    // 设置参数
    public function setData($data)
    {
        self::$data = $data;

        return $this;
    }

    // 设置参数的值
    //   如果参数存在 则替换
    public function setField($field, $value = null)
    {
        if(empty(self::$data)){
            self::$data = [];
        }
        self::$data[$field] = $value;

        return $this;
    }

    // 改变参数的键名称
    // 设置新参数的值 并 删除以前的那个参数
    public function changeField($field, $to_field, $value = null)
    {
        if(empty(self::$data)){
            self::$data = [];
        }
        if(is_null($value)){
            $value = self::$data[$field] ?? null;
        }

        // 设置新参数的值 并 删除以前的那个参数
        self::$data[$to_field] = $value;
        unset(self::$data[$field]);

        return $this;
    }

    // 设置登录用户
    public function setMyUser($myUser = [])
    {
        self::$myUser = $myUser;

        return $this;
    }

    #######################################################################################################
    ## 其他操作
    // 取得数据

    // 设置登录用户
    public function getError()
    {
        return $this->error;
    }

    // 获取当前ip
    public function getIp()
    {
        return self::$request->ip();
    }

    // $func 数据转换函数  如果为 true 则为 null 的时候也返回默认值
    public function getData($name = '', $def = null, $func = '')
    {
        $data = self::$data;
        if(empty($name)){
            return $data;
        }

        if(!isset($data[$name])){
            return $def;
        }
        /*if($data[$name]){
            if(empty($def)){
                return $data[$name];
            } else{
                return $def;
            }
        }*/
        // 传递为空字符串 接收为 null
        if(is_null($data[$name])){
            return $def;
        }

        // 特殊字段
        if(($name == 'page') && (!empty($this->page))){
            return $this->page;
        } elseif(($name == 'rows') && (!empty($this->rows))){
            return $this->rows;
        }

        // 已经经过安全过滤操作 （过滤xss）
        $value = $data[$name];
        if(empty($func)){
            return $value;
        }

        // php 7种数据类型
        // 一般不是数组或对象的操作
        // 默认操作方法是  trim
        if(in_array($func, ['trim', 'intval'])){
            $this->throwReturn(is_object($value) || is_array($value), '参数错误，'.$name.'不能是数组或对象！');

            // 如果是默认方法 trim 同时又是传递的是数字 则不做任何处理
            //$this->throwReturn(is_numeric($value) && $func=='trim','参数错误，'.$name.'必须是字符串！');
            if($func == 'trim' && is_numeric($value)){
                return $value;
            }
        }
        if(in_array($func, ['is_array', 'json_encode'])){
            $this->throwReturn(!is_array($value), '参数错误，'.$name.'必须是数组或对象');
            if($func == 'is_array'){
                return $value;
            } elseif($func == 'json_encode'){
                return $this->jsonChinese($value);
            }
        }

        return $func($value);
    }

    // 获取Header中的参数值
    public function getHeader(string $key = '', $default = null)
    {
        // HTTP请求头信息的名称不区分大小写，并且 _ 会自动转换为 -
        $result = self::$request->header($key);
        if(empty($result)) return $default;

        return $result;
    }

    // 验证
    public function validate($data, $rules, array $message = [], array $attr = [])
    {
        if(empty($rules)){
            return true;
        }

        // 验证
        $validator = \Validator::make($data, $rules, $message, $attr);
        if($validator->fails()){
            $messages = $validator->errors();

            return $this->_returnFail($messages->first());
        }

        return true;
    }

    // 设置 request
    public function request()
    {
        return self::$request;
    }

    // 转化json,中文不转化
    protected function jsonChinese(array $data = [])
    {
        return json_encode($data, JSON_UNESCAPED_UNICODE);
    }

    #######################################################################################################
    // 制作翻页
    public function getPages($total, $page, $rows)
    {
        $result = (new Page($total, $page, $rows))->show();

        return $result;
    }

    // 加载模板输出
    public function dispaly($template, $vars = [])
    {
        $vars     = empty($vars) ? self::$assign : (self::$assign ? array_merge(self::$assign, $vars) : $vars);
        $vars     = empty($vars) ? [] : $vars;
        $tpl_file = (isMobile() ? 'wap/' : '').$template;

        return view($tpl_file, $vars);
    }

    // 返回数据
    public function assign($name, $value = '')
    {
        if(is_array($name)){
            self::$assign = array_merge(self::$assign, $name);
        } else{
            self::$assign[$name] = $value;
        }

        return $this;
    }

    public function getAssign($name, $value = '')
    {
        return self::$assign[$name] ?? $value;
    }

    #######################################################################################################
    ## 异常

    // 抛出异常
    public function throwReturn($condition, $msg, $code = 400)
    {
        if($condition){
            throw new \RuntimeException($msg, $code);
        }
    }

    // 抛出异常
    public function throwIf($condition, $msg, $code = 400)
    {
        if($condition){
            throw new \RuntimeException($msg, $code);
        }
    }

    // 在初始化中，不会抛出异常，只能使用终止程序
    public function dieIf($condition, $msg, $code = 400, $is_encode = IS_ENCODE)
    {
        if($condition){
            $json = ['msg' => $msg, 'code' => $code, 'data' => [],];
            if($is_encode){
                //$json = ['data' => $this->encode($data)];
            } else{
                $json['access'] = 1; //不加密
            }

            $json = json_encode($json);
            die($json);
        }
    }

    #######################################################################################################
    // 返回错误
    protected function _returnFail($error)
    {
        $this->error = $error;

        return false;
    }

    // 获取用户以及权限
    protected function myUser($field = '')
    {
        $myUser = self::$myUser;
        if(empty($myUser)){
            $myUser = [];
            $token  = self::$request->header('token');
            if(!empty($token)){
                // TODO 为了避免解析以前的token报错（The payload is invalid.）
                try{
                    $myUser = Crypt::decryptString($token);
                    $myUser = json_decode($myUser, true);
                } catch(\Exception $e){
                    $myUser = [];
                }

                $this->throwIf(empty($user), 'token过期，请重新登录！！', LOGIN_ERROR);
                $this->throwIf(empty($user['ctime']), 'token过期，请重新登录！！', LOGIN_ERROR);

                // 查看登录的用户信息
                $userDb = new User();
                $info   = $userDb->isCache(true)->oneFind(['id' => $myUser['id']]); // ->recycle()
                $this->throwIf(empty($info), '登录过期，请重新登录！！', LOGIN_ERROR);
                $this->throwIf($info['status'] == -1, '登录过期，请重新登录！！', LOGIN_ERROR);
                $this->throwIf($info['status'] < 0, '登录过期，请重新登录！！', LOGIN_ERROR);
                $this->throwIf($info['status'] == 0, '对不起，你已经被禁用！！', LOGIN_ERROR);
                //$this->throwIf(empty($info), '用户不存在！！');
                //$this->throwIf($info['verify'] === 0, '你暂未通过审核！！');

                $myUser = is_object($info) ? $info->toArray() : $info;
                // 组合
                $myUser['uid'] = $myUser['id'];
            }

            self::$myUser = $myUser;
        }

        return $myUser[$field] ?? null;
    }
}
